`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2021/04/20 09:21:08
// Design Name: 
// Module Name: Controller
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module control32(
    
    //指令中的Opcode，Function_opcode
    input[5:0] Opcode,
    input[5:0] Function_opcode, //instruction[5:0]
    input[21:0] Alu_resultHigh,
    //是不是jr指令
    output Jr,
    //是不是j指令
    output Jmp,
    //jal
    output Jal, //jal or not
    output Branch, //beq or not
    output nBranch, //bne or not
    //我要把数据写入寄存器组，这个寄存器的编号来自于指令的哪一部分？rd or rt
    output RegDST, //1-->rd,0-->rt
 
    //是否有向寄存器组中写数据的权限
    output RegWrite, 
    //是否有向内存中写数据的权限
    output MemWrite,
    //ALU的第二个操作数是不是立即数？
    output ALUSrc,//1-->2nd data is immediate
    //这个指令是不是除了beq,bne,lw,sw的I型指令，也就是寄存器中的一个数要和立即数做运算
    output I_format,//1-->I format except beq,bne,lw,sw
    //是不是移位运算
    output Sftmd, //1->shift instruction
    //ALUOp
    output[1:0] ALUOp, //00->lw or sw,01-->beq or bne,10-->R format or other I format(need the funct)
    //这个是权限开启，我要把内存中或者IO设备中的数放到寄存器组中,这个信号可以代替原来的MemtoReg
    output MemorIOtoReg,
    //开启从内存中读取数据的权限
    output MemRead,
    //我要从IO中读取数据
    output IORead,
    //我要从IO中把数据写出去
    output IOWrite
    );

    //表示是不是R型指令，是不是LW,是不是SW
    wire R_format,LW,SW;
    //判断是不是R型指令
    assign R_format = (Opcode == 6'b000000) ? 1'b1 : 1'b0;
    //判断是不是LW
    assign LW = (Opcode == 6'b100011) ? 1'b1 : 1'b0;
    //判断是不是SW
    assign SW = (Opcode == 6'b101011) ? 1'b1 : 1'b0;
    //判断是不是jr
    assign Jr = ((Opcode == 6'b000000) && (Function_opcode == 6'b001000));
    //判断是不是j
    assign Jmp = (Opcode == 6'b000010) ? 1'b1 : 1'b0;
	//判断是不是jal
    assign Jal = (Opcode == 6'b000011) ? 1'b1 : 1'b0;
    //判断是不是beq
    assign Branch = (Opcode == 6'b000100) ? 1'b1 : 1'b0;
	//判断是不是bne
    assign nBranch = (Opcode == 6'b000101) ? 1'b1 : 1'b0;
	//判断写入寄存器编号来自于rd还是rt，只需要判断是不是R型指令就行了
    assign RegDST = R_format;
    
	//根据是不是lw,sw指令，和ALU的高位地址空间判断如下信号
    //是不是要写进RAM里？
    assign MemWrite = (SW && (Alu_resultHigh[21:0] != 22'h3FFFFF)) ? 1'b1 : 1'b0;
    //是不是要从RAM里读取数据？
    assign MemRead = (LW && (Alu_resultHigh[21:0] != 22'h3FFFFF)) ? 1'b1 : 1'b0;
    //是不是要从IO内存中读取数据？
    assign IORead = (LW && (Alu_resultHigh[21:0] == 22'h3FFFFF)) ? 1'b1 : 1'b0;
    //是不是要写到IO内存中？
    assign IOWrite = (SW && (Alu_resultHigh[21:0] == 22'h3FFFFF)) ? 1'b1 : 1'b0;
    assign MemorIOtoReg = IORead || MemRead;
    //有立即数参与运算的指令
    assign ALUSrc = (I_format || LW || SW);
	//判断是不是除了beq,bne,lw,sw的I型指令
    assign I_format = (Opcode[5:3] == 3'b001) ? 1'b1 : 1'b0;
	//判断是不是要向寄存器中写入数据
    assign RegWrite = (R_format || LW || Jal || I_format) && (!Jr);
	//判断是不是移位指令
    assign Sftmd = (R_format && ((Function_opcode == 6'b000000) || (Function_opcode == 6'b000010) ||(Function_opcode == 6'b000011) || (Function_opcode == 6'b000100) || (Function_opcode == 6'b000110) || (Function_opcode == 6'b000111))) ? 1'b1 : 1'b0;
	//生成ALUOp
    assign ALUOp = {(R_format || I_format),(Branch || nBranch)};
    
    

    
    
endmodule
